#include <VCL\VCL.h>
#pragma hdrstop

#include "EIC.h"
#include "uBarre.h"

#pragma package(smart_init)
#pragma resource "*.dfm"

#define BARRE_FIRST_MESSAGE_TOP     CalculPixelPourPPP(24) // Ordonnée du 1er message (ou du message par défaut)
#define BARRE_MESSAGE_LEFT          CalculPixelPourPPP(16) // Abscisse d'un message
#define BARRE_MESSAGE_WIDTH         CalculPixelPourPPP(345) // Taille d'un message
#define BARRE_IMAGE_MESSAGE_GAP     CalculPixelPourPPP(10) // Espace entre le bord droit le l'image et le début du message
#define BARRE_IMAGE_VERTICAL_GAP    CalculPixelPourPPP(6) // Espace vertical libre entre 2 images


void __fastcall TfrmBarre::SetMessages( const AnsiString& strMessages)
{
 TStringList *plstMsg;     // Liste des messages d'activité
 int         nNbMsg;       // Nombre de messages d'activité
 int         yTop;         // Ordonnée d'un message
 int         nNoMsg;       // N° d'un message (0 à nNbMsg-1)
 TLabel      *plblNew;     // Un composant TLabel qui représente un nouveau message
 TImage      *pimgNew;     //  "    "      TImage  "      "      l'image associée à un nouveau message
 int         nImgHeight;   // Hauteur de l'image d'un message
 int         nImgWidth;    // Largeur "     "     "      "
 int         nImgVSpacing; // Espace entre 2 messages


 plstMsg = NULL;
 try {
   // Taille d'une image de message
                    nImgWidth  = imgMsg0->Width;
   nImgVSpacing = ( nImgHeight = imgMsg0->Height) + BARRE_IMAGE_VERTICAL_GAP;

   // Stockage des messages
   plstMsg = new TStringList();
   plstMsg->Text = strMessages;
   if( ( m_nNbMessages = nNbMsg = plstMsg->Count) > 1)
   { //////////////////////////////////////////////////
     // Création des contrôles associés aux messages //
     ///////////////////////////<///////////////////////
     // Modification des contrôles existant pour un message unique
     // => Adaptation pour le 1er message de la liste des messages
     //    ... le libellé est cadré à gauche et en gras
     lblMsg0->Alignment   = taLeftJustify;
     lblMsg0->Font->Style = TFontStyles() << fsBold;
     lblMsg0->Left        = BARRE_MESSAGE_LEFT  + BARRE_IMAGE_MESSAGE_GAP + nImgWidth;
     lblMsg0->Width       = BARRE_MESSAGE_WIDTH - BARRE_IMAGE_MESSAGE_GAP - nImgWidth;
     lblMsg0->Caption     = plstMsg->Strings[ 0];

     //    ... et l'image "en cours" est visible
     imgMsg0->Left    = BARRE_MESSAGE_LEFT;
     imgMsg0->Top     = BARRE_FIRST_MESSAGE_TOP;
     imgMsg0->Visible = true;

     // => Création des contrôles suivants
     yTop = BARRE_FIRST_MESSAGE_TOP;
     for( nNoMsg = 1; nNoMsg < nNbMsg; nNoMsg++)
     { // ... image
       pimgNew = NULL;
       try {
         InsertControl( pimgNew = new TImage( this));
         pimgNew->Left   = BARRE_MESSAGE_LEFT;
         pimgNew->Top    = ( yTop += nImgVSpacing);
         pimgNew->Width  = nImgWidth;
         pimgNew->Height = nImgHeight;
         pimgNew->Tag    = nNoMsg;
         pimgNew->Parent = this;
       } catch(...) {
         delete pimgNew;
         #ifdef _DEBUG
           ShowMessage( "Avertir Xavier ou David !\nImpossible de créer le TImage de la barre.");
         #endif
         throw;
       }

       // ... libellé
       plblNew = NULL;
       try {
         InsertControl( plblNew = new TLabel( this));
         plblNew->AutoSize  = false;
         plblNew->Left      = BARRE_MESSAGE_LEFT  + nImgWidth + BARRE_IMAGE_MESSAGE_GAP;
         plblNew->Top       = yTop;
         plblNew->Width     = BARRE_MESSAGE_WIDTH - nImgWidth - BARRE_IMAGE_MESSAGE_GAP;
         plblNew->Alignment = taLeftJustify;
         plblNew->Tag       = nNoMsg;
         plblNew->Caption   = plstMsg->Strings[ nNoMsg];
         plblNew->Parent    = this;
       } catch(...) {
         delete plblNew;
         #ifdef _DEBUG
           ShowMessage( "Avertir Xavier ou David !\nImpossible de créer le TLabel de la barre.");
         #endif
         throw;
       }
     }

     // => Modification de la taille de la fenêtre (et de la position des infos et de la barre de défilement)
     Height          += ( nNbMsg = ( ( nNbMsg - 1) * nImgVSpacing));
     lblMsgInfo->Top += nNbMsg;
     pb->Top         += nNbMsg;
     lblMsgInfo2->Top += nNbMsg;
     pb2->Top         += nNbMsg;
   }
   else
   { ////////////////////////////////////////
     // Initialisation de l'unique message //
     ////////////////////////////////////////
     if( !strMessages.IsEmpty())
     { // Message spécifique
       // => On l'initialise (par défaut, le mesage est "Veuillez patienter S.V.P.")
       lblMsg0->Caption = strMessages;
     }
   }


   ////////////////////////////////////////
   // Initialisation du message en cours //
   ////////////////////////////////////////
   m_nCurrentMessage = 0;


   delete plstMsg;
   lblMsgInfo->Caption = "Veuillez patienter S.V.P.";
 } catch(...) {
   m_nNbMessages     = 0;
   m_nCurrentMessage = -1;
   delete plstMsg;
 }
} /* TfrmBarre::SetMessages() */


void __fastcall TfrmBarre::PrepareNextMessage()
{
 int              nControl;     // Indice d'un control de la fiche
 TGraphicControl* pCtrl;        // Un controle graphique de la fiche associé à un message
 int              nNextMessage; // N° du prochain message à préparer (aussi le TAG des controls associés au prochain message à préparerà
 TLabel*          plblCurrent;  // Composant TLabel associé au message en cours
 TImage*          pimgCurrent;  //     "     TImage    "    "     "    "    "
 TLabel*          plblNext;     //     "     TLabel    "    "     "    à préparer
 TImage*          pimgNext;     //     "     TImage    "    "     "    "    "

 #ifdef _DEBUG
  if (( m_nCurrentMessage + 1) >= m_nNbMessages)
    if (IS_MACHINE_INFORMATICIEN())
      {
        EICErreur("Un 'NextMessage' en trop");
        return;
      }
    else
      ASSERT( ( m_nCurrentMessage + 1) < m_nNbMessages);
  {
    TLabel* plbl = new TLabel( NULL); TImage* pimg = new TImage( NULL);
    ASSERT( dynamic_cast<TGraphicControl*>( plbl) && dynamic_cast<TGraphicControl*>( pimg));
    delete plbl; delete pimg;
  }
 #endif


 /////////////////////////////////////////////////////////////////////////
 // Recherche des composants associés aux messages actuel et à préparer //
 /////////////////////////////////////////////////////////////////////////
 plblCurrent  = plblNext = NULL;
 pimgCurrent  = pimgNext = NULL;
 nNextMessage = m_nCurrentMessage + 1;
 for( nControl = ControlCount; --nControl >= 0;)
   if( ( pCtrl = dynamic_cast<TGraphicControl*>( Controls[ nControl])) != NULL)
   {
     if( pCtrl->Tag == m_nCurrentMessage)
     { // Ce control est associé au message courant;
       ASSERT( dynamic_cast<TLabel*>( pCtrl) || dynamic_cast<TImage*>( pCtrl));

       if (dynamic_cast<TLabel*>( pCtrl))
         plblCurrent = (TLabel*)pCtrl;    // ... c'est le libellé du message
       else
       { // ... c'est l'image du statut du message
         pimgCurrent = (TImage*)pCtrl;
         // Olivier est passé par ici
         pimgCurrent->Transparent = true;
       }
     }
     else if( pCtrl->Tag == nNextMessage)
     { // Ce control est associé au message à préparer
       ASSERT( dynamic_cast<TLabel*>( pCtrl) || dynamic_cast<TImage*>( pCtrl));

       if( dynamic_cast<TLabel*>( pCtrl))
         plblNext = (TLabel*)pCtrl;        // ... c'est le libellé du message
       else
       { // ... c'est l'image du statut du message
         pimgNext = (TImage*)pCtrl;
         // Olivier est passé par ici
         pimgNext->Transparent = true;
       }
     }
   }
 ASSERT(pimgCurrent);
 ASSERT(pimgNext);
 ASSERT(plblCurrent);
 ASSERT(plblNext);

 /////////////////////////////////////////////////////////
 // Préparation des composants pour le prochain message //
 /////////////////////////////////////////////////////////
 if( pimgCurrent && pimgNext && plblCurrent && plblNext)
 { // => MAJ des images associées aux statut des messages
   pimgNext->Picture    = pimgCurrent->Picture; // Image "En cours"
   pimgCurrent->Picture = imgDone->Picture;     // Image "Terminé"
   // Olivier est passé par ici
   pimgNext->Transparent    = true;
   pimgCurrent->Transparent = true;

   // => MAJ des libellés des messages
   plblNext->Font          = plblCurrent->Font; // Passage du message "En cours" en gras
   plblCurrent->ParentFont = true;              // Restauration du message "Terminé" dans la fonte par défaut

   // => Stockage du message actif
   m_nCurrentMessage = nNextMessage;
 }
 lblMsgInfo->Caption = "Veuillez patienter S.V.P.";               // Réinitialisation du message d'information
 pb->Position = 0;                             // Réinitialisation de la barre de progression
 Refresh();                                    // Affichage des modifications
} /* TfrmBarre::PrepareNextMessage() */



__fastcall TfrmBarre::TfrmBarre( TForm* pfrmOwner)
: TForm( pfrmOwner ? pfrmOwner :
                     ( ( ( pfrmOwner = Screen->ActiveForm) != NULL) ?
                       pfrmOwner : ( pfrmOwner = Application->MainForm)
                     ))
{
 ASSERT(imgMsg0->Tag == 0);
 ASSERT(!imgMsg0->Visible);
 ASSERT(lblMsg0->Tag == 0);
 ASSERT(lblMsg0->Alignment == taCenter);
 ASSERT(lblMsg0->Left == BARRE_MESSAGE_LEFT);
 ASSERT(lblMsg0->Top == BARRE_FIRST_MESSAGE_TOP);

 pb->Step   = 1;
 pb->Left   = BARRE_MESSAGE_LEFT;
 pb->Width  = BARRE_MESSAGE_WIDTH;

 m_nNbMessages     = 0;
 m_nCurrentMessage = -1;
 m_Sablier = 0;
 if( pfrmOwner)
 { // Centrage du dialogue de progression par rapport au parent (centré horizontalement et au 1/3 de sa hauteur)
   Position = poDesigned;
   Left = pfrmOwner->Left + ( pfrmOwner->Width  - Width)  / 2; if( Left < 0) Left = 0;
   Top  = pfrmOwner->Top  + ( pfrmOwner->Height - Height) / 3; if( Top  < 0) Top  = 0;
 }
 else
   ASSERT( Position == poScreenCenter);

 m_pvTaskWindows = NULL;
 m_Sablier = new CSablier();
 m_Annule = false;
} /* TfrmBarre::TfrmBarre() */


__fastcall TfrmBarre::~TfrmBarre()
{
 ///////////////////////////////////////////
 // Réactivation des fenêtres de la tâche //
 ///////////////////////////////////////////
   Forms::EnableTaskWindows( m_pvTaskWindows);
   m_pvTaskWindows = NULL;
   if (m_Sablier)
    {
      delete m_Sablier;
      m_Sablier = 0;
    }
} /* TfrmBarre::~TfrmBarre() */

void __fastcall TfrmBarre::FormShow(TObject *Sender)
{
//   m_hwndActive    = ::GetActiveWindow(); ça doit servir à rien ?
   m_hwndActive    = Handle;
   m_pvTaskWindows = Forms::DisableTaskWindows( m_hwndActive);
}
//---------------------------------------------------------------------------


void __fastcall TfrmBarre::FormHide(TObject *Sender)
{
   Forms::EnableTaskWindows( m_pvTaskWindows);
   m_pvTaskWindows = NULL;
}
//---------------------------------------------------------------------------

//**************//
// Class CBarre //
//**************////////////////////////////////////////////////////////////////
//                                                                            //
//   Cette classe permet de gérer une barre de progression avec plusieurs     //
// messages d'activités et une jauge de progression.                          //
////////////////////////////////////////////////////////////////////////////////
__fastcall CBarre::CBarre(TForm* pfrmOwnerAndParent)
{
 m_pfrmOwnerAndParent = pfrmOwnerAndParent;
 m_pvfrmBarre         = NULL;
 m_dwMax              = 0;
 m_Position = 0;
 m_AfficherBoutonAnnuler = m_DoubleAffichage = false;
}



__fastcall CBarre::~CBarre()
{
 Close();
}



HWND __fastcall CBarre::GetHandle() const
{
  if (m_pvfrmBarre)
    return m_pvfrmBarre->Handle;
  return 0;
}



void __fastcall CBarre::SetMessageInfo(int Index,const AnsiString &strMsgInfo)
{
  ASSERT(m_pvfrmBarre);

  if (m_pvfrmBarre)
    {
      switch (Index)
        {
          case 1:
            m_pvfrmBarre->lblMsgInfo->Caption = strMsgInfo;
            break;
          case 2:
            m_pvfrmBarre->lblMsgInfo2->Caption = strMsgInfo;
            break;
          default:
            ASSERT(false);
        }
      Refresh();
    }
}



void __fastcall CBarre::SetMax(int Index,DWORD dwMax)
{
  switch (Index)
    {
      case 1:
        m_dwMax = dwMax;
        if (m_pvfrmBarre)
          {
            if (dwMax)
              {
                m_pvfrmBarre->pb->Position = 0;           //Pour pouvoir modifier le max sans planter
                m_pvfrmBarre->pb->Max = 1000;        //Pour être compatible Windows 95a qui est limité à 65535 pour le Max
                Position = 0;
              }
            m_pvfrmBarre->pb->Visible = dwMax;
            Application->ProcessMessages();
          }
        break;
      case 2:
        m_dwMax2 = dwMax;
        if (m_pvfrmBarre)
          {
            m_pvfrmBarre->pb2->Position = 0;           //Pour pouvoir modifier le max sans planter
            m_pvfrmBarre->pb2->Max = 1000;        //Pour être compatible Windows 95a qui est limité à 65535 pour le Max
            Position2 = 0;
          }
        break;
      default:
        ASSERT(false);
    }
}



void __fastcall CBarre::ChangerMax(DWORD dwMax)
{
  m_dwMax = dwMax;
}



void __fastcall CBarre::SetPosition(int Index,DWORD dwPosition)
{
  switch (Index)
    {
      case 1:
        *this = dwPosition;
        break;
      case 2:
        ASSERT( m_pvfrmBarre);

        if (m_pvfrmBarre)
          {
            #ifdef _DEBUG
              if (dwPosition > m_dwMax2)
                {
                  if (!IS_MACHINE_INFORMATICIEN() || (dwPosition >= m_dwMax2 + 5))
                    return;
                  AnsiString Chaine = AnsiString("La deuxième position de la barre (") + (int)dwPosition + ")\nest supérieure au Max (" + (int)m_dwMax2 + ")";
                  EICAttention(Chaine.c_str());
                }
            #endif
            m_Position2 = dwPosition;
            if (m_dwMax2)
              m_pvfrmBarre->pb2->Position = (int)(double)(((double)dwPosition / (double)m_dwMax2) * (double)1000.0);   //Pour être compatible Windows 95a qui est limité à 65535 pour le Max
            if (AfficherBoutonAnnuler || !(m_Position2 % 100))
             Refresh();   //On réaffiche la fenêtre tous les 100
          }
        break;
      default:
        ASSERT(false);
    }
}



int __fastcall CBarre::GetCurrentMessage() const
{
 ASSERT(m_pvfrmBarre);

 if (m_pvfrmBarre)
   return m_pvfrmBarre->CurrentMessage;
 return -1;
}



void __fastcall CBarre::Open()
{
 ASSERT(!m_pvfrmBarre);

 Close();

 ASSERT(!m_pvfrmBarre);

 try {
   m_pvfrmBarre = new TfrmBarre( m_pfrmOwnerAndParent);

   ASSERT(m_pvfrmBarre);

   m_pvfrmBarre->Caption       = m_strTitre;
   m_pvfrmBarre->Messages      = m_strMessages;
   m_pvfrmBarre->pb->Max       = 1000;
   m_pvfrmBarre->pb->Visible   = m_dwMax;
   m_pvfrmBarre->Visible       = true;
   Application->ProcessMessages();
 } catch(...) {
   delete m_pvfrmBarre;
   m_pvfrmBarre = NULL;
 }
}



void __fastcall CBarre::Close()
{
  if (m_pvfrmBarre)
    {
      delete m_pvfrmBarre;
      m_pvfrmBarre = NULL;
    }
  ::BringWindowToTop( Screen->ActiveForm ? Screen->ActiveForm->Handle : Application->Handle);
}



void __fastcall CBarre::operator++()
{
// ASSERT( m_pvfrmBarre);

 if (m_pvfrmBarre)
  Position = Position + 1;
}



void __fastcall CBarre::operator=(DWORD dwPos)
{
 ASSERT( m_pvfrmBarre);

 if( m_pvfrmBarre)
 {
  #ifdef _DEBUG
    if (dwPos > m_dwMax)
      {
      	if (!IS_MACHINE_INFORMATICIEN() || (dwPos >= m_dwMax + 5))
      	  return;
      	AnsiString Chaine = AnsiString("La position de la barre (") + (int)dwPos + ")\nest supérieure au Max (" + (int)m_dwMax + ")";
      	EICAttention(Chaine.c_str());
      }
  #endif
   m_Position = dwPos;
   if (m_dwMax)
     m_pvfrmBarre->pb->Position = (int)(double)(((double)dwPos / (double)m_dwMax) * (double)1000.0);   //Pour être compatible Windows 95a qui est limité à 65535 pour le Max
   if (AfficherBoutonAnnuler || !(m_Position % 100))
    Refresh();   //On réaffiche la fenêtre tous les 100
 }
}



void __fastcall CBarre::NextMessage()
{
  ASSERT(m_pvfrmBarre);

  if (m_pvfrmBarre)
   m_pvfrmBarre->PrepareNextMessage();    // La progression est possible
  Position = 0;
}



void __fastcall CBarre::Refresh() const
{
  ASSERT(m_pvfrmBarre);

  if (m_pvfrmBarre)
    Application->ProcessMessages();        // Refraîchissement de la barre
}



void __fastcall CBarre::SetDoubleAffichage(bool AfficherDeuxiemeBarre)
{
  bool AncienAfficherBoutonAnnuler = AfficherBoutonAnnuler;

  ASSERT(m_pvfrmBarre);

  if (m_DoubleAffichage ^ AfficherDeuxiemeBarre)
    {
      if (AncienAfficherBoutonAnnuler)
        AfficherBoutonAnnuler = false;                 //Pour remettre le bouton Annuler à la bonne hauteur
      m_DoubleAffichage = AfficherDeuxiemeBarre;
      if (AfficherDeuxiemeBarre)
        m_pvfrmBarre->Height += CalculPixelPourPPP(45);
      else
        m_pvfrmBarre->Height -= CalculPixelPourPPP(45);
      m_pvfrmBarre->pb2->Visible = AfficherDeuxiemeBarre;
      m_pvfrmBarre->lblMsgInfo2->Visible = AfficherDeuxiemeBarre;
      if (AncienAfficherBoutonAnnuler)
        AfficherBoutonAnnuler = true;                  //Pour remettre le bouton Annuler à la bonne hauteur
    }
}



void __fastcall CBarre::SetAfficherBoutonAnnuler(bool bAfficherBoutonAnnuler)
{
  ASSERT(m_pvfrmBarre);

  if (m_AfficherBoutonAnnuler ^ bAfficherBoutonAnnuler)
    {
      m_AfficherBoutonAnnuler = bAfficherBoutonAnnuler;
      if (bAfficherBoutonAnnuler)
        m_pvfrmBarre->Height += CalculPixelPourPPP(25);
      else
        m_pvfrmBarre->Height -= CalculPixelPourPPP(25);
      m_pvfrmBarre->bAnnuler->Visible = bAfficherBoutonAnnuler;
      m_pvfrmBarre->bAnnuler->Top = m_pvfrmBarre->ClientHeight - CalculPixelPourPPP(30);
    }
}



void __fastcall CBarre::SetAnnule(bool bAnnule)
{
  ASSERT(m_pvfrmBarre);

  m_pvfrmBarre->m_Annule = bAnnule;
}



bool __fastcall CBarre::GetAnnule() const
{
  ASSERT(m_pvfrmBarre);

  return m_pvfrmBarre->m_Annule;
}



void __fastcall TfrmBarre::bAnnulerClick(TObject *Sender)
{
  m_Annule = true;
}



